package com.ato.CommonClass.StringClass;

/**
 * @author wangjing
 * @create 2021--10--01--21:02
 */

/**
 * String
 * 1：内部定义声明了final char value[]  不可比性，final用法。类不能继承，方法不能重写，变量不可修改，则为常量
 * 重新赋值时或者链接操作，比如 += ，其实是新建一个内容，把新建内容的地址值赋值给变量
 * 其实感觉和JS差不多，
 * 体现：
 * 2：支持序列化的 实现了  Serializable : 可序列化
 * 3：实现了可比较的，Comparable
 * 4：使用new的方式，那么 就是在堆空间中分别创建了，内存地址都不一样了。因此
 *      String s0 = new String("123") 和 String s1 = "abc" 肯定是不一样的，s0是常量池中的内存地址，s1是堆内存中的内存地址，是不一样的
 *      注意：String是重写了equals的，因此 如果用s0.equals(s1) 那就是等的
 */
public class StringTest {
    public static void main(String[] args) {

        String s1 = "abc"; // 由于是字面量创建。区别于new
        String s2 = "abc";
        System.out.println(s1 == s2);
        /**
         == 为比较内存地址。因此可以看出
         字符串是存放在方法区的常量池，而常量池是不会存储两个相同的字符，因此，这两个变量指向的内存地址一致
         而使用字面创建的变量再去修改重新赋值时，其实是重新在字符串常量池中又新建一个，因为字符串其实是一个final char value[]的数组。长度时定了的
         使用 "xx".replace() 去替换更改时，也是一样的，都是去新建
         不能修改，只能新建。在将新建的内容所在的内存地址赋值
         */
        s1 = "456";

        System.out.println(s1); // 456
        System.out.println(s2); // abc
        String s4 = "abc";
        String replace = s4.replace("a", "m");
        System.out.println(replace);
        System.out.println("======= new 创建 ===========");
        String s5 = new String("abc");
        String s6 = new String("abc");
        System.out.println(s5 == s6);//  两个new的 内存地址都不一样
        System.out.println(s5 == s2); //  也是两个内存地址，一个是常量池中的内存地址，一个是堆内存中的内存地址
        System.out.println(s5.equals(s2)); //  String是重写了equals的，因此 如果用s0.equals(s1) 那就是等的
    }
}
